package com.gitee.wsl.data.pool.sample

import com.gitee.wsl.data.pool.Pool

open class SimplePool<T>(
    maxPoolSize: Int
) : Pool<T> {

    private var mPool: Array<Any?>

    override var capacity = 0

    init {
        if (maxPoolSize <= 0) {
            throw IllegalArgumentException("The max pool size must be > 0")
        }

        mPool = arrayOfNulls(maxPoolSize)
    }

    @Suppress("UNCHECKED_CAST")
    override fun acquire(): T? {
        if (capacity > 0) {
            val lastPooledIndex = capacity - 1
            val instance = mPool[lastPooledIndex] as T
            mPool[lastPooledIndex] = null
            capacity--
            return instance
        }
        return null
    }

    override fun release(instance: T): Boolean {
        if (DEBUG) {
            if (isInPool(instance)) {
                throw IllegalStateException("Already in the pool!")
            }
        }
        if (capacity < mPool.size) {
            mPool[capacity] = instance
            capacity++
            return true
        }
        return false
    }

    @Suppress("NAME_SHADOWING")
    override fun releaseAll(variables: List<T>) {
        val count = variables.size
        for (i in 0 until count) {
            val instance = variables[i]
            if (DEBUG) {
                check(!isInPool(instance)) { "Already in the pool!" }
            }
            if (capacity < mPool.size) {
                mPool[capacity] = instance
                capacity++
            }
        }
    }

    private fun isInPool(instance: T): Boolean {
        for (i in 0 until capacity) {
            if (mPool[i] == instance) {
                return true
            }
        }
        return false
    }

    override fun dispose() = releaseAll(mPool.take(capacity) as List<T>)

    companion object{
        private const val DEBUG = false
    }
}

fun <T> Pool.Companion.sample(maxPoolSize: Int):Pool<T> = SimplePool(maxPoolSize)